package com.naiterui.ehp.bs.patient.service.impl;

import cn.hutool.core.util.IdcardUtil;
import com.naiterui.common.repository.page.CustomizedPageConvertor;
import com.naiterui.common.repository.page.Page;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.constants.CommonConstant;
import com.naiterui.ehp.bp.domain.Patient;
import com.naiterui.ehp.bp.domain.PatientInquirer;
import com.naiterui.ehp.bp.domain.PatientInquirerInfo;
import com.naiterui.ehp.bp.domain.PatientPersonDoctor;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.notice.AppNoticeUtil;
import com.naiterui.ehp.bs.doctor.dao.IPatientPersonDoctorDao;
import com.naiterui.ehp.bs.doctor.repository.IDrPatientGroupDetailRepository;
import com.naiterui.ehp.bs.doctor.service.IPatientService;
import com.naiterui.ehp.bs.doctor.vo.PatientVo;
import com.naiterui.ehp.bs.patient.exception.ExceptionCodes;
import com.naiterui.ehp.bs.patient.repository.IApPatientPersonDoctorRepository;
import com.naiterui.ehp.bs.patient.repository.IApPatientRepository;
import com.naiterui.ehp.bs.patient.repository.IPatientInquirerRepository;
import com.naiterui.ehp.bs.patient.repository.PatientInquirerRepository;
import com.naiterui.ehp.bs.patient.service.IPatientSyncService;
import com.naiterui.ehp.bs.patient.utils.ConfigKeyUtil;
import com.naiterui.ehp.bs.patient.vo.requestparam.PatientInquirerParam;
import com.naiterui.ehp.bs.patient.vo.requestparam.PatientParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class PatientSyncServiceImpl implements IPatientSyncService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PatientSyncServiceImpl.class);
    @Autowired
    private IApPatientRepository apPatientRepository;
    @Autowired
    private IPatientInquirerRepository patientInquirerRepository;
    @Autowired
    private IApPatientPersonDoctorRepository apPatientPersonDoctorRepository;
    @Autowired
    private IPatientPersonDoctorDao patientPersonDoctorDao;
    @Autowired
    private IPatientService patientService;
    @Autowired
    private PatientInquirerRepository patientInquirerNewRepository;
    @Autowired
    private IDrPatientGroupDetailRepository drPatientGroupDetailRepository;

    // 查询医生患者是否存在关系
    public ResponseVO queryDoctorPatientIsFriend(Long doctorId, Long patientId){
        Integer isFriend = 0;
        // 查询是否有关系
        PatientPersonDoctor patientPersonDoctor = apPatientPersonDoctorRepository.findFirstByPersonPKPatientIdAndPersonPKDoctorId(patientId, doctorId);
        if(patientPersonDoctor != null && patientPersonDoctor.getRelationFlag() == PatientPersonDoctor.RELATION_FLAG_NORMALITY){
            isFriend = 1;
        }
        Map<String, Object> result = new HashMap<>();
        result.put("isFriend", isFriend);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, result);
    }

    // 发送系统消息
    public void sendSystemMessage(Long patientId, Long doctorId, Integer type, Long userId) {
        try{
            // 处理患者、就诊人关系
            if(patientId != null && userId != null){
                dealPatientInquire(userId, patientId);
            }
            // 发送消息推送
            String host = ConfigKeyUtil.getString("amp.host.url");
            if(type == 1){   // 添加患者
                AppNoticeUtil.NewPatient newPatient = new AppNoticeUtil.NewPatient(patientId);
                AppNoticeUtil.sendSingleNotice(host, doctorId, AppNoticeUtil.NoticeType.DR_NEW_PATIENT, newPatient);
            }else if(type == 2){  // 问题关闭
                // 给医生推送
                AppNoticeUtil.NewPatient newPatient = new AppNoticeUtil.NewPatient(patientId);
                AppNoticeUtil.sendSingleNotice(host, doctorId, AppNoticeUtil.NoticeType.DR_FINISH_SESSION, newPatient);
                // 给患者推送
                AppNoticeUtil.NewDotcor newDotcor = new AppNoticeUtil.NewDotcor(doctorId);
                AppNoticeUtil.sendSingleNotice(host, patientId, AppNoticeUtil.NoticeType.PT_FINISH_SESSION, newDotcor);
            }else if(type == 3){  // 问题未回复
                // 给医生推送
                AppNoticeUtil.NewPatient newPatient = new AppNoticeUtil.NewPatient(patientId);
                AppNoticeUtil.sendSingleNotice(host, doctorId, AppNoticeUtil.NoticeType.DR_MESSAGE_NO_REPLY, newPatient);
                // 给患者推送
                AppNoticeUtil.NewDotcor newDotcor = new AppNoticeUtil.NewDotcor(doctorId);
                AppNoticeUtil.sendSingleNotice(host, patientId, AppNoticeUtil.NoticeType.PT_MESSAGE_NO_REPLY, newDotcor);
            }else if(type == 4){   // 首页发送文章
                // 给患者推送
                AppNoticeUtil.NewDotcor newDotcor = new AppNoticeUtil.NewDotcor(doctorId);
                AppNoticeUtil.sendSingleNotice(host, patientId, AppNoticeUtil.NoticeType.PT_MESSAGE_SEND_ARTICLE, newDotcor);
            }
        }catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // 医生查询待审核患者列表(分页)
    public PageVO<PatientVo> queryDoctorPatientAuditPage(Long doctorId, PageParamVO pageParamVO){
        // 与医生绑定的患者，按时间段查，并分页
        Page<PatientPersonDoctor> patientPersonDoctor = patientPersonDoctorDao.getByPeriods(doctorId, pageParamVO);
       // 医生-患者关联集合
        List<PatientPersonDoctor> patientPersonalList = patientPersonDoctor.getResult();
        if (patientPersonalList == null || patientPersonalList.size() <= 0) {
            return new PageVO<>();
        }
        List<Long> lstPatientId = new ArrayList<>();
        for(PatientPersonDoctor patient : patientPersonalList){
            lstPatientId.add(patient.getPersonPK().getPatientId());
        }
        try{
            List<PatientVo> lstPatient = patientService.getPatientsByDoctorId(doctorId, lstPatientId);
            return CustomizedPageConvertor.pageConvert(patientPersonDoctor, lstPatient);
        }catch (Exception e){
            return new PageVO<>();
        }
    }

    // 查询医生今日患者
    public Long queryDoctorPatientToday(Long doctorId){
        return patientPersonDoctorDao.getTodayPatientCountNew(doctorId);
    }

    // 医生解除患者关系
    @Transactional(rollbackFor = Exception.class)
    public ResponseVO removeDoctorPatient(Long doctorId, Long patientId){
        // 查询是否有关系
        PatientPersonDoctor patientPersonDoctor = apPatientPersonDoctorRepository.findFirstByPersonPKPatientIdAndPersonPKDoctorId(patientId, doctorId);
        if(patientPersonDoctor == null){
            return PublicService.returnResponseVO(ExceptionCodes.DATA_ERR, "医生和患者不存在关系");
        }
        // 修改状态
        if(patientPersonDoctor.getRelationFlag() != PatientPersonDoctor.RELATION_FLAG_DSH){
            apPatientPersonDoctorRepository.auditDoctorPatient(PatientPersonDoctor.RELATION_FLAG_DSH, doctorId, patientId);
        }
        // 删除分组信息
        drPatientGroupDetailRepository.deleteByDoctorIdAndPatientId(doctorId, patientId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    // 医生审核患者（接受）
    @Transactional(rollbackFor = Exception.class)
    public ResponseVO auditDoctorPatient(Long doctorId, Long patientId){
        // 查询是否有关系
        PatientPersonDoctor patientPersonDoctor = apPatientPersonDoctorRepository.findFirstByPersonPKPatientIdAndPersonPKDoctorId(patientId, doctorId);
        if(patientPersonDoctor == null || patientPersonDoctor.getRelationFlag() == PatientPersonDoctor.RELATION_FLAG_DELETE){
            return PublicService.returnResponseVO(ExceptionCodes.DATA_ERR, "医生和患者不存在关系不能审核");
        }
        // 修改状态
        if(patientPersonDoctor.getRelationFlag() != PatientPersonDoctor.RELATION_FLAG_NORMALITY){
            apPatientPersonDoctorRepository.auditDoctorPatient(PatientPersonDoctor.RELATION_FLAG_NORMALITY, doctorId, patientId);
        }
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    // 添加患者信息
    @Transactional(rollbackFor = Exception.class)
    public void savePatient(PatientParam patientParam){
        patientParam.setNickName(StringUtils.isEmpty(patientParam.getNickName()) ? "普通用户" : patientParam.getNickName());
        // 根据id查询是否存在
        Patient patient = apPatientRepository.findByIdAndPlatform(patientParam.getPatientId(), patientParam.getPlatform());
        if(patient == null){  // 添加
            apPatientRepository.savePatient(patientParam.getPatientId(), patientParam.getNickName(), patientParam.getNickName(), patientParam.getGender(),
                    patientParam.getPhone(), patientParam.getHeadUrl(), new Date(), patientParam.getPlatform(), Patient.PATIENT_CALCEL_NO_FOCUS,
                    null, null, null);
        }else{   // 修改
            apPatientRepository.updatePatient(patientParam.getNickName(), patientParam.getNickName(), patientParam.getGender(), patientParam.getPhone(),
                    patientParam.getHeadUrl(), null, null, null, patientParam.getPatientId());
        }
    }

    // 添加就诊人
    @Transactional(rollbackFor = Exception.class)
    public ResponseVO savePatientInquirer(PatientInquirerParam patientInquirerParam){
        // 判断患者是否存在
        Patient patient = apPatientRepository.findByIdAndPlatform(patientInquirerParam.getPatientId(), patientInquirerParam.getPlatform());
        if(patient == null){
            return PublicService.returnResponseVO(ExceptionCodes.DATA_ERR, "患者不存在，无法添加患者就诊人");
        }
        Long patientId = patientInquirerParam.getPatientId();
        Long inquirerId = patientInquirerParam.getInquirerId();
        // 查询就诊人是否存在
        PatientInquirerInfo patientInquirerInfo = patientInquirerRepository.findByIdAndPlatform(patientInquirerParam.getInquirerId(), patientInquirerParam.getPlatform());
        // 性别
        Integer gender = null;
        // 出生日期
        Date birthdayDate = null;
        try{
            gender = StringUtils.isEmpty(patientInquirerParam.getIdCard()) ? null : IdcardUtil.getGenderByIdCard(patientInquirerParam.getIdCard());
            birthdayDate = StringUtils.isEmpty(patientInquirerParam.getIdCard()) ? null : IdcardUtil.getBirthDate(patientInquirerParam.getIdCard());
        }catch (Exception e){
            LOGGER.error("添加患者就诊人  获取idCard数据有误");
        }
        String birthday = birthdayDate == null ? null : DateUtil.parseDateToString(birthdayDate, "yyyy-MM-dd");
        if(patientInquirerInfo == null){  // 添加
            patientInquirerRepository.savePatientInquirer(patientInquirerParam.getInquirerId(), patientInquirerParam.getPatientId(), patientInquirerParam.getRelation(),
                    patientInquirerParam.getName(), patientInquirerParam.getIdCard(), gender, birthday, patientInquirerParam.getPhone(), patientInquirerParam.getAddress(),
                    patientInquirerParam.getContactName(), patientInquirerParam.getContactPhone(), patientInquirerParam.getIsDefault(),
                    patientInquirerParam.getPlatform(), PatientInquirerInfo.ACCOUNT_STATUS_YES, new Date());
        }else{  // 修改
            patientInquirerRepository.updatePatientInquirer(patientInquirerParam.getRelation(), patientInquirerParam.getName(), patientInquirerParam.getIdCard(),
                    patientInquirerParam.getPhone(), patientInquirerParam.getAddress(), patientInquirerParam.getContactName(), patientInquirerParam.getContactPhone(),
                    patientInquirerParam.getIsDefault(), gender, birthday, patientInquirerParam.getInquirerId(), patientInquirerParam.getPatientId());
        }
        // 处理患者联系人信息
        patientInquirerParam.setHeadUrl(patient.getHeadUrl());
        saveInquirerPatient(patientInquirerParam);
        // 处理患者、就诊人关系
        LOGGER.info("添加患者就诊人  处理患者、就诊人关系  patientId: {}, inquirerId: {}", patientId, inquirerId);
        dealPatientInquire(patientId, inquirerId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patientInquirerParam);
    }

    // 处理患者、就诊人关系
    public void dealPatientInquire(Long patientId, Long inquirerId){
        LOGGER.info("dealPatientInquire  处理患者、就诊人关系  patientId: {}, inquirerId: {}", patientId, inquirerId);
        PatientInquirer patientInquirer = patientInquirerNewRepository.findByInquirerId(inquirerId);
        if(patientInquirer == null){   // 之前没有数据
            patientInquirer = new PatientInquirer();
            patientInquirer.setPatientId(patientId);
            patientInquirer.setInquirerId(inquirerId);
            patientInquirer.setStatus(0);
            LOGGER.info("dealPatientInquire  处理患者、就诊人关系  patientId: {}, inquirerId: {}", patientInquirer.getPatientId(), patientInquirer.getInquirerId());
            patientInquirerNewRepository.save(patientInquirer);
        }else{   // 修改数据
            patientInquirer.setPatientId(patientId);
            patientInquirer.setInquirerId(inquirerId);
            patientInquirer.setStatus(0);
            LOGGER.info("dealPatientInquire  处理患者、就诊人关系  patientId: {}, inquirerId: {}", patientInquirer.getPatientId(), patientInquirer.getInquirerId());
            patientInquirerNewRepository.update(patientInquirer);
        }
    }

    // 处理患者联系人信息
    public void saveInquirerPatient(PatientInquirerParam patientInquirerParam){
        // 根据id查询是否存在
        Patient patient = apPatientRepository.findByIdAndPlatform(patientInquirerParam.getInquirerId(), patientInquirerParam.getPlatform());
        String name = StringUtils.isEmpty(patientInquirerParam.getName()) ? "普通用户" : patientInquirerParam.getName();
        // 年龄
        Integer age = null;
        // 性别
        Integer gender = null;
        // 出生日期
        Date birthdayDate = null;
        try{
            age = StringUtils.isEmpty(patientInquirerParam.getIdCard()) ? null : IdcardUtil.getAgeByIdCard(patientInquirerParam.getIdCard());
            gender = StringUtils.isEmpty(patientInquirerParam.getIdCard()) ? null : IdcardUtil.getGenderByIdCard(patientInquirerParam.getIdCard());
            birthdayDate = StringUtils.isEmpty(patientInquirerParam.getIdCard()) ? null : IdcardUtil.getBirthDate(patientInquirerParam.getIdCard());
        }catch (Exception e){
            LOGGER.error("添加患者就诊人  获取idCard数据有误");
        }
        String birthday = birthdayDate == null ? null : DateUtil.parseDateToString(birthdayDate, "yyyy-MM-dd");
        if(patient == null){  // 添加
            apPatientRepository.savePatient(patientInquirerParam.getInquirerId(), name, name, gender, patientInquirerParam.getPhone(), patientInquirerParam.getHeadUrl(), new Date(),
                    patientInquirerParam.getPlatform(), Patient.PATIENT_CALCEL_NO_FOCUS, patientInquirerParam.getIdCard(), birthday, age);
        }else{   // 修改
            apPatientRepository.updatePatient(name, name, gender, patientInquirerParam.getPhone(), patientInquirerParam.getHeadUrl(), patientInquirerParam.getIdCard(), birthday, age,
                    patientInquirerParam.getInquirerId());
        }
    }

    // 删除就诊人信息
    @Transactional(rollbackFor = Exception.class)
    public void deletePatientInquirer(PatientInquirerParam patientInquirerParam){
        patientInquirerRepository.deletePatientInquirer(PatientInquirerInfo.STATUS_DELETE, patientInquirerParam.getInquirerId(), patientInquirerParam.getPatientId());
    }

    public int getAge(Date birth) {
        Calendar cal = Calendar.getInstance();
        int thisYear = cal.get(Calendar.YEAR);
        int thisMonth = cal.get(Calendar.MONTH);
        int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birth);
        int birthYear = cal.get(Calendar.YEAR);
        int birthMonth = cal.get(Calendar.MONTH);
        int birthdayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
        int age = thisYear - birthYear;
        // 未足月
        if (thisMonth <= birthMonth) {
            // 当月
            if (thisMonth == birthMonth) {
                // 未足日
                if (dayOfMonth < birthdayOfMonth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }
}
